package com.getpebble.android.framework;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.text.TextUtils;
import com.getpebble.android.common.core.trace.AnalyticsLogger.Event;
import com.getpebble.android.common.core.trace.Trace;
import com.getpebble.android.common.core.util.ProcessUtil.PebbleProcess;
import com.getpebble.android.common.model.PblDevice;
import com.getpebble.android.framework.notification.NotificationSender.NotificationDemoType;
import java.util.concurrent.LinkedBlockingQueue;

public class PblFrameworkInterface {
    public static final String TAG = PblFrameworkInterface.class.getSimpleName();
    private boolean mBinding = false;
    private final Handler mBindingHandler = new Handler(Looper.getMainLooper());
    private final Runnable mBindingTimeoutRunnable;
    private boolean mBound = false;
    private final ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (service == null) {
                Trace.error(PblFrameworkInterface.TAG, "service binder was null - not binding to framework");
                return;
            }
            Trace.debug(PblFrameworkInterface.TAG, "onServiceConnected pre");
            synchronized (PblFrameworkInterface.this) {
                PblFrameworkInterface.this.mFrameworkMessenger = new Messenger(service);
                PblFrameworkInterface.this.mBound = true;
                PblFrameworkInterface.this.mBinding = false;
                PblFrameworkInterface.this.mBindingHandler.removeCallbacks(PblFrameworkInterface.this.mBindingTimeoutRunnable);
                PblFrameworkInterface.this.setReplyMessenger();
                if (PblFrameworkInterface.this.mMessageQueue.size() > 0) {
                    for (int i = 0; i < PblFrameworkInterface.this.mMessageQueue.size(); i++) {
                        Message msg = (Message) PblFrameworkInterface.this.mMessageQueue.poll();
                        Trace.verbose(PblFrameworkInterface.TAG, "De-queueing message: " + msg.what);
                        PblFrameworkInterface.this.sendMessage(msg);
                    }
                }
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            Trace.debug(PblFrameworkInterface.TAG, "onServiceDisconnected pre");
            synchronized (PblFrameworkInterface.this) {
                PblFrameworkInterface.this.mFrameworkMessenger = null;
                PblFrameworkInterface.this.mBound = false;
                PblFrameworkInterface.this.mBinding = false;
                PblFrameworkInterface.this.mBindingHandler.removeCallbacks(PblFrameworkInterface.this.mBindingTimeoutRunnable);
            }
        }
    };
    private Context mContext = null;
    private FrameworkEventReceiver mFrameworkEventReceiver = null;
    private Messenger mFrameworkMessenger = null;
    private final LinkedBlockingQueue<Message> mMessageQueue = new LinkedBlockingQueue(20);
    private final PebbleProcess mProcess;

    public PblFrameworkInterface(Context context, PebbleProcess process) throws IllegalArgumentException {
        if (context == null) {
            throw new IllegalArgumentException("Context cannot be null!");
        }
        Trace.debug(TAG, "Creating FrameworkEventReceiver");
        this.mFrameworkEventReceiver = new FrameworkEventReceiver(context);
        this.mContext = context;
        this.mProcess = process;
        this.mBindingTimeoutRunnable = new Runnable() {
            public void run() {
                Trace.info(PblFrameworkInterface.TAG, "Timed out binding: Unbind");
                synchronized (PblFrameworkInterface.this) {
                    PblFrameworkInterface.this.mBinding = false;
                    PblFrameworkInterface.this.unBindService();
                }
            }
        };
    }

    public synchronized void bindService() {
        if (!(this.mBound || this.mBinding)) {
            Trace.info(TAG, "bindService (not bound)");
            this.mBinding = true;
            this.mBindingHandler.postDelayed(this.mBindingTimeoutRunnable, 1500);
            try {
                this.mContext.bindService(new Intent(this.mContext, PblFrameworkService.class), this.mConnection, 1);
            } catch (Exception e) {
                Trace.error(TAG, "Error binding to framework service", e);
            }
        }
    }

    public synchronized void unBindService() {
        if (this.mBound && !this.mBinding) {
            Trace.info(TAG, "unBindService (bound)");
            try {
                this.mContext.unbindService(this.mConnection);
            } catch (Exception e) {
                Trace.info(TAG, "Error unbinding service", e);
            }
        }
    }

    public boolean connectToDevice(PblDevice device) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        }
        Message msg = Message.obtain(null, 1, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("device_extra", device);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean disconnectFromDevice(PblDevice device) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        }
        Message msg = Message.obtain(null, 2, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("device_extra", device);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean startDiscovery() {
        return sendMessageWithRequest(4);
    }

    public boolean stopDiscovery() {
        return sendMessageWithRequest(5);
    }

    public boolean sendDemoNotification(NotificationDemoType demoType) {
        Message msg = Message.obtain(null, 6, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putSerializable("notification_type_extra", demoType);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean updateFirmware(PblDevice device, Uri firmwareUri) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        } else if (firmwareUri == null) {
            throw new IllegalArgumentException("'firmwareUri' cannot be null!");
        } else {
            Message msg = Message.obtain(null, 7, 0, 0);
            Bundle bundle = new Bundle();
            bundle.putParcelable("device_extra", device);
            bundle.putParcelable("firmware_uri_extra", firmwareUri);
            msg.setData(bundle);
            return sendMessage(msg);
        }
    }

    public boolean updateFirmwareForRecovery(PblDevice device) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        }
        Message msg = Message.obtain(null, 10, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("device_extra", device);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean installApp(PblDevice device, Uri appUri, boolean autoStart, boolean allowReinstall) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        } else if (appUri == null) {
            throw new IllegalArgumentException("'appUri' cannot be null!");
        } else {
            Message msg = Message.obtain(null, 8, 0, 0);
            Bundle bundle = new Bundle();
            bundle.putParcelable("device_extra", device);
            bundle.putParcelable("uri_extra", appUri);
            bundle.putBoolean("auto_start_extra", autoStart);
            bundle.putBoolean("allow_reinstall_extra", allowReinstall);
            msg.setData(bundle);
            Trace.debug(TAG, "Sending app install message for: " + device);
            return sendMessage(msg);
        }
    }

    public boolean installLanguage(PblDevice device, Uri fileUri, String isoLocale, int languageVersion) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null");
        } else if (fileUri == null) {
            throw new IllegalArgumentException("'fileuri' cannot be null");
        } else if (isoLocale == null) {
            throw new IllegalArgumentException("'isoLocale' cannot be null");
        } else {
            Message msg = Message.obtain(null, 21, 0, 0);
            Bundle bundle = new Bundle();
            bundle.putParcelable("device_extra", device);
            bundle.putParcelable("uri_extra", fileUri);
            bundle.putString("iso_locale_extra", isoLocale);
            bundle.putInt("language_version_extra", languageVersion);
            bundle.putString("file_name_extra", "lang");
            msg.setData(bundle);
            Trace.debug(TAG, "Sending language (file) install message for: " + device);
            return sendMessage(msg);
        }
    }

    public boolean uninstallApp(PblDevice device, String uuid) throws IllegalArgumentException {
        if (device == null) {
            throw new IllegalArgumentException("'device' cannot be null!");
        } else if (TextUtils.isEmpty(uuid)) {
            throw new IllegalArgumentException("'uuid' cannot be null or empty!");
        } else {
            Message msg = Message.obtain(null, 9, 0, 0);
            Bundle bundle = new Bundle();
            bundle.putParcelable("device_extra", device);
            bundle.putString("app_uuid_extra", uuid);
            msg.setData(bundle);
            Trace.debug(TAG, "sending uninstall message for " + device);
            return sendMessage(msg);
        }
    }

    public boolean fetchAppInfo(Uri uri) {
        Message msg = Message.obtain(null, 11, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("uri_extra", uri);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean sendAnalyticsEvent(Event event) {
        Message msg = Message.obtain(null, 16, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("analytics_event_extra", event);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean sendAnalyticsUploadRequest() {
        return sendMessageWithRequest(17);
    }

    public boolean sendAnalyticsEnableDisableRequest(boolean enable) {
        Message msg = Message.obtain(null, 18, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putBoolean("analytics_enable_extra", enable);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean sendAnalyticsReinitRequest() {
        return sendMessageWithRequest(19);
    }

    public boolean requestCoreDump(PblDevice device) {
        Message msg = Message.obtain(null, 12, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("device_extra", device);
        msg.setData(bundle);
        Trace.debug(TAG, "sending core dump request for " + device);
        return sendMessage(msg);
    }

    public boolean requestLogDump(PblDevice device) {
        if (!this.mBound) {
            return false;
        }
        Message msg = Message.obtain(null, 13, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putParcelable("device_extra", device);
        msg.setData(bundle);
        Trace.debug(TAG, "sending log dump request for " + device);
        return sendMessage(msg);
    }

    public boolean startDeveloperConnection() {
        Trace.verbose(TAG, "Sending REQUEST_START_DEVELOPER_CONN");
        return sendMessageWithRequest(14);
    }

    public boolean stopDeveloperConnection() {
        Trace.verbose(TAG, "Sending REQUEST_STOP_DEVELOPER_CONN");
        return sendMessageWithRequest(15);
    }

    public boolean pingDeveloperConnectionProxy() {
        return sendMessageWithRequest(20);
    }

    public boolean setVerboseLogcat(boolean enabled) {
        Message msg = Message.obtain(null, 22, 0, 0);
        Bundle bundle = new Bundle();
        bundle.putBoolean("logcat_verbose_extra", enabled);
        msg.setData(bundle);
        return sendMessage(msg);
    }

    public boolean requestConnectionStateProcessing() {
        return sendMessageWithRequest(23);
    }

    private boolean setReplyMessenger() {
        Trace.debug(TAG, "setReplyMessenger()");
        if (PebbleProcess.UI.equals(this.mProcess)) {
            Message msg = Message.obtain(null, 3, 0, 0);
            msg.replyTo = this.mFrameworkEventReceiver.getMessenger();
            return sendMessage(msg);
        }
        Trace.verbose(TAG, "Not setting reply messenger; not UI process");
        return false;
    }

    private synchronized boolean sendMessage(Message msg) {
        boolean z = false;
        synchronized (this) {
            bindService();
            if (msg == null) {
                throw new IllegalArgumentException("'msg' cannot be null!");
            }
            try {
                if (this.mFrameworkMessenger != null) {
                    this.mFrameworkMessenger.send(msg);
                    z = true;
                }
            } catch (RemoteException re) {
                Trace.info(TAG, "Failed to send message.", re);
                this.mBound = false;
            }
            Trace.verbose(TAG, "Queueing message: " + msg.what);
            if (this.mMessageQueue.remainingCapacity() == 0) {
                Trace.debug(TAG, ".. queue full; removing " + ((Message) this.mMessageQueue.poll()).what);
            }
            this.mMessageQueue.offer(msg);
            unBindService();
            bindService();
        }
        return z;
    }

    private boolean sendMessageWithRequest(int command) {
        return sendMessage(Message.obtain(null, command, 0, 0));
    }
}
